﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Hiro.ActivationPoints;
using Hiro.Interfaces;

namespace Hiro.Loaders
{
    /// <summary>
    /// Represents a <see cref="IPropertyResolver"/> type that uses conventions to determine
    /// the dependencies that should be mapped to a given set a properties.
    /// </summary>
    public class ConventionOverConfigurationPropertyResolver : PropertyResolver
    {
        /// <summary>
        /// Initializes a new instance of the ConventionOverConfigurationPropertyResolver class.
        /// </summary>
        public ConventionOverConfigurationPropertyResolver()
        {
            Enabled = true;
        }

        /// <summary>
        /// Gets or sets a value indicating whether or not the resolver is enabled.
        /// </summary>
        /// <value>The boolean value that indicates whether or not the current resolver is enabled.</value>
        public bool Enabled { get; set; }

        /// <summary>
        /// Determines which dependency should be used for property injection.
        /// </summary>
        /// <param name="targetProperty">The target property.</param>
        /// <param name="dependencyContainer>The dependency map that describes the list of dependencies in the application.</param>
        /// <returns>An <see cref="IDependency"/> instance if the dependency can be found; otherwise, it will return <c>null</c>.</returns>
        public override IDependency Resolve(PropertyInfo targetProperty, IDependencyContainer dependencyContainer)
        {
            if (!Enabled)
                return null;

            // If possible, use the service that matches the property name
            var conventionBasedDependency = new Dependency(targetProperty.Name, targetProperty.PropertyType);

            if (dependencyContainer.Contains(conventionBasedDependency))
                return conventionBasedDependency;

            var defaultDependency = new Dependency(string.Empty, targetProperty.PropertyType);

            // Use the default service if the original result fails
            return dependencyContainer.Contains(defaultDependency) ? defaultDependency : null;
        }
    }
}
